import java.io.*;
import java.net.*;
import java.util.*;

public class LicenseServer {
    private static final int MAX_USERS = 10; // 最大用户数
    static HashMap<String, Integer> licenseUsage = new HashMap<>(); // 许可证使用情况
    private static final long REPORT_INTERVAL = 3 * 60 * 1000; // 报告间隔时间，单位：毫秒
    static HashMap<String, Long> softwareStatus = new HashMap<>(); // 软件A的状态

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8889);
            System.out.println("服务器开始工作...");

            // 定时清理已断开连接的客户端
            cleanDisconnectedClients();

            // 定时检查软件A状态
            checkSoftwareStatus();

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Client connected: " + clientSocket);

                // 处理客户端连接的逻辑
                LicenseServerHandler handler = new LicenseServerHandler(clientSocket);
                handler.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static synchronized boolean checkLicense(String serialNumber) {
        // 检查序列号是否有效
        // 这里检查使用人数是否已达上限
        Integer usage = licenseUsage.getOrDefault(serialNumber, 0);

        // 在判断序列号是否有效
        // 这里判断序列号长度是否为10
        if (serialNumber.length() != 10) {
            return false;
        }

        // 检查当前连接的用户数是否超过最大允许用户数
        if (usage >= MAX_USERS) {
            return false;
        }

        // 更新许可证使用情况
        licenseUsage.put(serialNumber, usage + 1);
        return true;
    }

    private static void cleanDisconnectedClients() {
        // 定时清理已断开连接的客户端
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                Iterator<Map.Entry<String, Integer>> iterator = licenseUsage.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Integer> entry = iterator.next();
                    if (entry.getValue() <= 0) {
                        iterator.remove();
                    }
                }
            }
        };

        // 每隔一段时间执行一次清理任务
        Timer timer = new Timer();
        timer.schedule(task, 0, REPORT_INTERVAL);
    }

    private static void checkSoftwareStatus() {
        // 定时检查软件A状态
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                long currentTime = System.currentTimeMillis();
                for (Map.Entry<String, Long> entry : softwareStatus.entrySet()) {
                    String softwareId = entry.getKey();
                    long lastReportTime = entry.getValue();
                    if (currentTime - lastReportTime > REPORT_INTERVAL * 2) {
                        // 软件A超过一定时间未报告状态，视为崩溃，从许可证使用人数中剔除
                        // 这里设定为报告时间间隔的两倍
                        licenseUsage.computeIfPresent(softwareId, (k, v) -> v - 1);
                        softwareStatus.remove(softwareId);
                    }
                }
            }
        };

        // 每隔一段时间执行一次状态检查任务
        Timer timer = new Timer();
        timer.schedule(task, 0, REPORT_INTERVAL);
    }
}

class LicenseServerHandler extends Thread {
    private Socket clientSocket;

    public LicenseServerHandler(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);

            // 询问客户端是否有序列号
            out.println("是否拥有序列号? [y/n]");

            // 读取客户端回复
            String hasSerialNumber = in.readLine().toLowerCase();

            if (hasSerialNumber.equals("y")) {
                // 用户已有序列号，读取并验证序列号
                String inputSerialNumber = in.readLine();
                boolean authorized = LicenseServer.checkLicense(inputSerialNumber);
                if (authorized) {
                    out.println("AUTHORIZED");
                    // 记录软件A的状态
                    LicenseServer.softwareStatus.put(clientSocket.getInetAddress().toString(), System.currentTimeMillis());
                } else {
                    out.println("DENIED");
                }
            } else {
                // 用户没有序列号，读取用户名、口令和许可证类型，并返回序列号
                String input = in.readLine();
                String[] inputs = input.split(":");
                String username = inputs[0];
                String password = inputs[1];
                String licenseType = inputs[2];

                // 假设这里是根据用户名、口令和许可证类型生成的序列号
                String serialNumber = generateSerialNumber(username, password, licenseType);

                // 返回序列号给客户端
                out.println(serialNumber);

                String inputSerialNumber = in.readLine();
                boolean authorized = LicenseServer.checkLicense(inputSerialNumber);
                if (authorized) {
                    out.println("AUTHORIZED");
                    // 记录软件A的状态
                    LicenseServer.softwareStatus.put(clientSocket.getInetAddress().toString(), System.currentTimeMillis());
                } else {
                    out.println("DENIED");
                }
            }

            // 关闭连接
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String generateSerialNumber(String username, String password, String licenseType) {
        // 根据用户名、口令和许可证类型生成序列号，这里简化为随机生成10位数字序列号
        StringBuilder serialNumber = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            serialNumber.append(random.nextInt(10));
        }
        return serialNumber.toString();
    }
}
